#include "client.h"

#include <algorithm>

#include <gl/glew.h>
#define GLFW_DLL
#include <gl/glfw.h>

#include "gamestate.h"
#include "renderer/renderer.h"
#include "simulation.h"

#include "entities/entity.h"
#include "entities/improvement.h"
#include "entities/tile.h"

#include "gui/gui.h"
#include "gui/guimessage.h"

Client* client;

void Client::Initialise(int clientID, bool human){
    this->clientID = clientID;
    this->human = human;

    prevTime = GetTickCount();

    cameraKeys.push_back('W');
    cameraKeys.push_back('S');
    cameraKeys.push_back('A');
    cameraKeys.push_back('D');
    cameraKeys.push_back('F');
    cameraKeys.push_back('R');
    cameraKeys.push_back('Z');
    cameraKeys.push_back('X');
    cameraKeys.push_back('T');
    cameraKeys.push_back('G');
    cameraKeys.push_back('P');
}

void Client::Update(){
    // blah
}

// Mouse input ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Client::MouseMoved(){
    if(client_state == PLACING){
        int id = renderer->Pick(mx, my);
        if(gamestate->GetTileByID(id)){
            simulation->MoveHoverImprovement(id);
        }
    }
}
void Client::SetMousePosition(int x, int y){
    mdx = x - mx;
    mdy = (GLHeight - y) - my;
    mx = x;
    my = GLHeight - y;
}

void Client::Click(int mousebutton){
    int id = renderer->Pick(mx, my);
    GUIMessage* guiMessage = gui->Click(id);

    if(guiMessage){
        CancelPlacing();
        ProcessGUIMessage(guiMessage);
        return;
    }

    if(client_state == PLACING){
        Entity* target = gamestate->GetEntity(id);
        if(!target){
            CancelPlacing();
            return;
        }
        switch(target->GetType()){
            case ET_TILE:{
                int hover_id = gamestate->GetHoverImprovementID();
                if(simulation->PlaceImprovement(hover_id)){
                    EndPlacing();
                    return;
                }
                else{
                    CancelPlacing();
                    return;
                }
                break;
            }
            default:{
                return;
            }
        }
    }

    simulation->ProcessOrder(id, mousebutton);
    gui->BuildGUI();
}

// IMPROVEMENT PLACING /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Client::BeginPlacing(std::string name){
    simulation->CreateHoverImprovement(name);
    client_state = PLACING;
}

void Client::EndPlacing(){
    simulation->SelectEntity(gamestate->GetHoverImprovementID());
    gamestate->SetHoverImprovementID(-1);
    client_state = AWAITING_ORDERS;
    gui->BuildGUI();
}

void Client::CancelPlacing(){
    gamestate->DeleteImprovement(gamestate->GetHoverImprovementID());
    gamestate->SetHoverImprovementID(-1);
    client_state = AWAITING_ORDERS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Client::ProcessOrder(GUIMessage* message){
    if(message->s == "resume"){
        simulation->ChangeImprovementConstructionPriority(message->i);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Client::ProcessGUIMessage(GUIMessage* message){
    std::string type = message->type;
    std::cout<<"Message recieved: "<<message->type<<", "<<message->s<<std::endl;
    if(type == "build"){
        simulation->Build(message->s);
        gui->BuildGUI();
    }
    else if(type == "improve"){
        BeginPlacing(message->s);
    }
    else if(type == "order"){
        ProcessOrder(message);
    }
    else{
        std::cout<<"Client: GUI message ignored!"<<std::endl;
    }
}

// Keyboard Handler ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Client::KeyDown(int key, bool down){
    if(down == true){
        if(key == '`'){
            simulation->TestRoadCreation();
        }
        else if(key == GLFW_KEY_ENTER){
            simulation->EndTurn();
            gui->EndTurn();
        }
//        for(int ck : cameraKeys){
//            if(ck == key){
//                renderer->ProcessKey(key);
//                return;
//            }
//        }
        if(std::find(cameraKeys.begin(), cameraKeys.end(), key)!=cameraKeys.end()){
            renderer->ProcessKey(key);
        }
    }
}

